package com.ruoyi.common.utils.bean;

import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 传入需要校验的实体类对象,检验必填参数是否为空或者null
 */
@Slf4j
public class ClassPropertyHandler<T> {

    private Field[] fields = new Field[]{};

    private Field[] superFields = new Field[]{};

    private T t;

    private Class clazz;

    public ClassPropertyHandler(T t) {
        this.t = t;
        this.fields = t.getClass().getDeclaredFields();
        this.superFields = t.getClass().getSuperclass().getDeclaredFields();
        this.clazz = t.getClass();
    }

    /**
     * 获取所有get方法 方法名
     *
     * @return
     */
    private List<String> getGetMethodName() {
        List<String> list = new ArrayList<>();
        Field[] allFields = ArrayUtils.addAll(fields, superFields);
        for (Field field : allFields) {
            //可自定义注解,标识必填字段
            Annotation annotation = field.getAnnotation(NotBlank.class);
            if (26 == field.getModifiers() || annotation == null) {
                continue;
            }
            char[] cs = field.getName().toCharArray();
            //首字母大写
            cs[0] -= 32;
            list.add("get" + String.valueOf(cs));
        }
        return list;
    }

    /**
     * 获取所有get方法 方法名
     *
     * @return
     */
    private List<Map<String, String>> getGetMethodNameAndAnnotationValue() {
        List<Map<String, String>> list = new ArrayList<>();
        Field[] allFields = ArrayUtils.addAll(fields, superFields);
        for (Field field : allFields) {
            Map<String, String> map = new HashMap<>();
            //可自定义注解,标识必填字段
            NotBlank notBlankAnnotation = field.getAnnotation(NotBlank.class);
            NotNull notNullAnnotation = field.getAnnotation(NotNull.class);

            if (26 == field.getModifiers() || (notBlankAnnotation == null && notNullAnnotation == null)) {
                continue;
            }
            char[] cs = field.getName().toCharArray();
            //首字母大写
            cs[0] -= 32;

            String message = null;
            if (notBlankAnnotation != null) {
                message = notBlankAnnotation.message();
            } else if (notNullAnnotation != null) {
                message = notNullAnnotation.message();
            }

            map.put("get" + String.valueOf(cs), message);
            list.add(map);
        }
        return list;
    }

    /**
     * 判断实体类属性值那些必填字段为空
     *
     * @return 返回空表示 必须有值的属性都满足需求 其他看返回值
     */
    public String hasNullOrEmptyPropertyValue() {
        String result = "";
        List<String> list = getGetMethodName();
        for (String methodName : list) {
            try {
                Method method = clazz.getMethod(methodName);
                Object res = method.invoke(t, null);
                if (res == null || "".equals(res)) {
                    //把 "get"截掉
                    String property = methodName.substring(3);
                    char[] chars = property.toCharArray();
                    //首字母变小写
                    chars[0] += 32;
                    result = result + ", " + String.valueOf(chars);
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isBlank(result)) {
            return result;
        }

        log.info("{} 的属性: {} 值为空或者null", clazz.getSimpleName(), result.substring(2));
        return result.substring(2) + " cannot be empty";
    }

    /**
     * 判断实体类属性值那些必填字段为空
     *
     * @return 返回空表示 必须有值的属性都满足需求 其他看返回值
     */
    public String hasNullOrEmptyValue() {
        AtomicReference<String> result = new AtomicReference<>("");
        List<Map<String, String>> list = getGetMethodNameAndAnnotationValue();
        for (Map<String, String> map : list) {
            map.forEach((k, v) -> {
                try {
                    String methodName = k;
                    Method method = clazz.getMethod(methodName);
                    Object res = method.invoke(t, null);
                    if (res == null || "".equals(res)) {
                        //把 "get"截掉
                        String property = methodName.substring(3);
                        char[] chars = property.toCharArray();
                        //首字母变小写
                        chars[0] += 32;
                        // result.set(v + ", " + String.valueOf(chars));
                        result.set(result.get() + (StringUtils.isBlank(result.get()) ? "" : ",") + v);
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            });

        }
        if (StringUtils.isBlank(result.get())) {
            return result.get();
        }

        log.info("{} 的属性值为空或者null: {}", clazz.getSimpleName(), result.get());
        return result.get();
    }
}